home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i020: make - a re-implementation of the UNIX make utility, Part01/02
- Message-ID: <11027@xanth.cs.odu.edu>
- Date: 17 Jan 90 23:16:34 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
- Lines: 2168
- Approved: tadguy@cs.odu.edu (Tad Guy)
-
- Submitted-by: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
- Posting-number: Volume 90, Issue 020
- Archive-name: unix/make/part01
-
- - A modified Make, the ubiquitous (sp?) one, with some bugs removed
- as reported in comp.os.minix, and an extra sourcefile searching
- feature. May also be useful when compiling NetHack 3.0.
-
- Freely_Distributable=Greetings(Not_For_Any_Commercial_Purpose)->
- Olaf.Seibert;
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 2)."
- # Contents: Makefile README README.amiga an check.c h.h input.c
- # macro.c main.c make.n reader.c rules.c
- # Wrapped by tadguy@xanth on Wed Jan 17 18:16:22 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(230 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# Makefile for make (Amiga Aztec version for use with PDC)
- X
- XCFLAGS=-Damiga #-Dpdc
- XCC=cc
- X
- XOBJS = main.o make.o rules.o reader.o \
- X input.o macro.o check.o
- X
- Xm: $(OBJS)
- X ln -o m $(OBJS) -lc
- X
- Xdf0:test:df1:test
- Xtest1:file1 file2
- END_OF_FILE
- if test 230 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(1803 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- XFollowing is a repost of the public domain 'make' that I posted
- Xto net.sources a couple of months ago. I have fixed a few bugs, and
- Xadded some more features, and the resulting changes amounted to
- Xabout as much text as the whole program (hence the repost).
- X
- XFor those that missed the net.sources posting, this is a public domain
- Xre-implementation of the UNIX make program. There is no manual included;
- Xfor documentation, refer to a UNIX manual, or the source.
- X
- XHere is a list of the changes made:
- X
- Xi) If '-' (ignore) or '@' (silent) where used at the start
- X of a command, their effect was not turned off for the following
- X commands.
- Xii) A special target (.SUFFIXES, .PRECIOUS) or a rule (.c.o, .a.o),
- X if first in the file would be taken as the default target.
- X This resulted in error messages like "Don't know how to
- X make .c", because things like .SUFFIXES were being made.
- X This was further complicated by ---
- Xiii) Special target lines with no dependents (ie. .SUFFIXES:\n)
- X were not clearing out the existing dependents like
- X they should.
- Xiv) Default rules could not be redefined because of the error
- X checking for commands being defined twice. Now you are
- X allowed to define a target beinging with '.', having
- X no dependents with commands.
- Xv) The -q option didn't do the time comparison correctly,
- X or clear the variable used to keep track of this. Thus
- X it didn't work very well.
- Xvi) The syntax ${..} for macro's supported by UNIX make was
- X not supported.
- Xvii) There wuz a couple of spelling errors.
- Xviii) When make checked for implicit rules on targets without
- X a suffix, there were problems. (Note: The ~ feature of
- X UNIX make wasn't and still isn't supported)
- Xix) The -n option did not print @ lines like it was supposed to.
- Xx) :: added. (See UNIX manual)
- Xxi) $? added. (see UNIX manual)
- END_OF_FILE
- if test 1803 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'README.amiga' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README.amiga'\"
- else
- echo shar: Extracting \"'README.amiga'\" \(4397 characters\)
- sed "s/^X//" >'README.amiga' <<'END_OF_FILE'
- XThis program is the public domain Make program which appeared on
- Xmod.sources, Volume 7, number 91. I have ported it to the Amiga under
- XManx Aztec C version 3.40a. This short document assumes you know
- XMake, and simply points out the Amiga specific features of the
- Xprogram. The supported switches are listed in the comment block at
- Xthe beginning of module main.c. I offer no apologies for the fact that
- XI ran the code through "indent -i4 -nfc1" on the 4.3BSD system at work
- Xbefore I started working on it.
- X The program has been compiled under Manx Aztec C Version 3.40.
- XIt uses Manx's fexecv() function to execute commands and get
- Xtheir return value, and the Manx dos_packet() function to send an
- XAmigaDOS packet to the file system for touch'ing purposes. Lattice
- Xrecompilers need to change these (at least). Peculiar features
- Xof the Amiga version are:
- X
- X(1) The Amiga-specific sections of the code are #ifdef'd on the symbol
- X amiga (note the lower case). I endorse Fred Fish's effort to
- X have system and compiler-supplied #define's in lower case to
- X ensure no collisions with user-supplied ones.
- X(2) The file rules.c, routine makerules(), contains the definitions of
- X the default built-in rules. For the Amiga, these are equivalent to
- X the Makefile:
- X
- X CC = cc
- X CFLAGS =
- X AS = as
- X AFLAGS =
- X
- X .c.o:
- X $(CC) $(CFLAGS) $<
- X .s.o:
- X $(AS) $(AFLAGS) -o $@ $<
- X
- X (indented for clarity only). Thus, one could conceivably do:
- X make CC=lc CFLAGS= AS=asm
- X to run this make under Lattice C.
- X(3) If the file S:builtins.make exists, its contents are read in
- X instead of the built-in rules defined in makerules(). Thus, you
- X can use different default rules on different disks and change
- X the default rules without recompiling make.
- X(4) A Control-D typed during execution of a command by make will cause
- X an abort with exit status 1 AFTER the completion of that command.
- X Control-C is an immediate abort, as you might expect.
- X(5) Not really Amiga specific, but worth mentioning, is that characters
- X special both to the local operating system (such as : in AmigaDOS) and
- X to make may be used in the makefile by preceding them with \
- X to temporarily override their special meaning. For example, to tell
- X make that RAM:foo depends on AC:foo.c, write:
- X
- X RAM\:foo : AC\:foo.c
- X
- X(6) The Aztec fexecv() function, which is used by make to execute its
- X commands, only works on programs in directories stored along the
- X AmigaDOS PATH, so make sure your PATH includes the appropriate
- X directories.
- X
- X Finally, I added one new feature in the non-machine-specific code:
- Xthe name of the makefile can be a single dash "-", in which case a
- Xmakefile is read from the standard input.
- X About the only feature of "real" make missing here is the
- Xsemicolon construct which allows a pair of lines such as the .c.o:
- Xrule and command above to be written as one line, viz:
- X .c.o: ; $(CC) $(CFLAGS) $<
- X
- XEnjoy! Bug reports in the Amiga-specific stuff should be directed to
- Xme; others should go to caret@fairlight.OZ, the author of the rest of it.
- XBy the way, this code is superior to the Manx-supplied make--more switches
- Xand a better parser; in fact, this make will handle the Makefile for
- XMicroGnuEmacs while Manx make chokes on the ln command.
- X
- X Steve Walton
- X ametek!walton@csvax.caltech.edu (ARPA)
- X WALTON@CALTECH (BITNET)
- X ...!ucbvax!sun!megatest!ametek!walton
- X
- XSome notes by Olaf Seibert, KosmoSoft:
- X
- XI adapted this version of make to PDC, and enhanced it a little. In
- Xparticular, if a line end with a backslash, the following newline and
- Xleading white space of the next line are now ignored. Previously, the
- Xnewline was merely turned into a space. Also, comparison of filenames now
- Xis case-insignificant. Makefiles need not be internally consistent in the
- Xcase of filenames. Also, the builtin rules are slightly different, for use
- Xwith PDC.
- X
- X CC = ccx -c
- X CFLAGS =
- X AS = ccx -c
- X AFLAGS =
- X
- X .c.o:
- X $(CC) $(CFLAGS) $<
- X .s.o:
- X $(AS) $(AFLAGS) $<
- X
- X /*OIS*0.80*/
- X
- XI took out the \: feature, which worked only in target names, and not in
- Xprerequisite files. Instead, I added a more rational interpretation of
- Xcolons. There is now at most one colon possible in a target name, which may
- Xnot contain any spaces.
- X
- XI incorporared a few bug fixes relating to $< and $*, from the minix newsgroup.
- XI added a new feature: the .PATH special target. See manual.
- X
- END_OF_FILE
- if test 4397 -ne `wc -c <'README.amiga'`; then
- echo shar: \"'README.amiga'\" unpacked with wrong size!
- fi
- # end of 'README.amiga'
- fi
- if test -f 'an' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'an'\"
- else
- echo shar: Extracting \"'an'\" \(2210 characters\)
- sed "s/^X//" >'an' <<'END_OF_FILE'
- X.*
- X.* Macro package for NRO in KosmoSoft version
- X.*
- X.nr h 5 @" header indent
- X.nr i 10 @" normal text indent
- X.nr s @ni-@nh @" section heading indent (to the LEFT)
- X.*
- X.de TH
- X.in @nh;.rm 80-@nh;.he |$0($1)|$2|$0($1)|
- X.fo |$3|-#-|$4|
- X.in @ni;.rm 80-@ni
- X.ta +0 +5
- X.en
- X.* Paragraph
- X.de PP
- X.sp 1;.ne 2;.ti +5
- X.en
- X.* Bulleted Paragraph. Needs .RE after last para.
- X.* Must be last on line. Relies on first tab stop.
- X.de BP
- X.br;.in @ni+5;.ti -3;o@t@@
- X.en
- X.* Section Heading
- X.de SH
- X.sp 1;.ne 3;.ti -@@ns;.bo "$0 $1 $2 $3 $4 $6 $6 $7 $8 $9
- X.br
- X.en
- X.* SubSection
- X.de SS
- X.br;.ne 2;.ti -@@ns+1/2;$0 $1 $2 $3 $4 $5 $6 $7 $8 $9
- X.br
- X.en
- X.* Relative indent Start
- X.de RS
- X.in +0$0
- X.en
- X.* Relative indent End
- X.de RE
- X.in @ni
- X.en
- X.* Italics
- X.de I
- X.it 1
- X$0 $1 $2 $3 $4 $5 $6 $7 $8 $9
- X.en
- X.* Bold
- X.de B
- X.bo 1
- X$0 $1 $2 $3 $4 $5 $6 $7 $8 $9
- X.en
- X.* Underline
- X.de U
- X.ul 1
- X$0 $1 $2 $3 $4 $5 $6 $7 $8 $9
- X.en
- X.* UC
- X.de UC
- X.* Empty
- X.en
- X.* Italics and Roman
- X.de IR
- X.if !''$0' .it "$0
- X.if !''$1' $1
- X.if !''$2' .it "$2
- X.if !''$3' $3
- X.if !''$4' .it "$4
- X.if !''$5' $5
- X.if !''$6' .it "$6
- X.if !''$7' $7
- X.if !''$8' .it "$8
- X.if !''$9' $9
- X.en
- X.* Roman and Italic
- X.de RI
- X.if !''$0' $0
- X.if !''$1' .it "$1
- X.if !''$2' $2
- X.if !''$3' .it "$3
- X.if !''$4' $4
- X.if !''$5' .it "$5
- X.if !''$6' $6
- X.if !''$7' .it "$7
- X.if !''$8' $8
- X.if !''$9' .it "$9
- X.en
- X.* Bold and Roman
- X.de BR
- X.if !''$0' .bo "$0
- X.if !''$1' $1
- X.if !''$2' .bo "$2
- X.if !''$3' $3
- X.if !''$4' .bo "$4
- X.if !''$5' $5
- X.if !''$6' .bo "$6
- X.if !''$7' $7
- X.if !''$8' .bo "$8
- X.if !''$9' $9
- X.en
- X.* Bold and Italic
- X.de BI
- X.if !''$0' .bo "$0
- X.if !''$1' .it "$1
- X.if !''$2' .bo "$2
- X.if !''$3' .it "$3
- X.if !''$4' .bo "$4
- X.if !''$5' .it "$5
- X.if !''$6' .bo "$6
- X.if !''$7' .it "$7
- X.if !''$8' .bo "$8
- X.if !''$9' .it "$9
- X.en
- X.* Italic and Bold
- X.de IB
- X.if !''$0' .it "$0
- X.if !''$1' .bo "$1
- X.if !''$2' .it "$2
- X.if !''$3' .bo "$3
- X.if !''$4' .it "$4
- X.if !''$5' .bo "$5
- X.if !''$6' .it "$6
- X.if !''$7' .bo "$7
- X.if !''$8' .it "$8
- X.if !''$9' .bo "$9
- X.en
- X.* Italic and Roman
- X.de IR
- X.if !''$0' .it "$0
- X.if !''$1' $1
- X.if !''$2' .it "$2
- X.if !''$3' $3
- X.if !''$4' .it "$4
- X.if !''$5' $5
- X.if !''$6' .it "$6
- X.if !''$7' $7
- X.if !''$8' .it "$8
- X.if !''$9' $9
- X.en
- X.* SMall, do nothing
- X.de SM
- X$0 $1 $2 $3 $4 $5 $6 $7 $8 $9
- X.en
- END_OF_FILE
- if test 2210 -ne `wc -c <'an'`; then
- echo shar: \"'an'\" unpacked with wrong size!
- fi
- # end of 'an'
- fi
- if test -f 'check.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'check.c'\"
- else
- echo shar: Extracting \"'check.c'\" \(2152 characters\)
- sed "s/^X//" >'check.c' <<'END_OF_FILE'
- X/*
- X * Check structures for make.
- X */
- X
- X#include <stdio.h>
- X#include "h.h"
- X
- X
- X/*
- X * Prints out the structures as defined in memory. Good for check
- X * that you make file does what you want (and for debugging make).
- X */
- Xvoid
- Xprt()
- X{
- X register struct name *np;
- X register struct depend *dp;
- X register struct line *lp;
- X register struct cmd *cp;
- X register struct macro *mp;
- X
- X
- X for (mp = macrohead; mp; mp = mp->m_next)
- X fprintf(stderr, "%s = %s\n", mp->m_name, mp->m_val);
- X
- X fputc('\n', stderr);
- X
- X for (np = namehead.n_next; np; np = np->n_next) {
- X if (np->n_flag & N_DOUBLE)
- X fprintf(stderr, "%s::\n", np->n_name);
- X else
- X fprintf(stderr, "%s:\n", np->n_name);
- X if (np == firstname)
- X fprintf(stderr, "(MAIN NAME)\n");
- X for (lp = np->n_line; lp; lp = lp->l_next) {
- X fputc(':', stderr);
- X for (dp = lp->l_dep; dp; dp = dp->d_next)
- X fprintf(stderr, " %s", dp->d_name->n_name);
- X fputc('\n', stderr);
- X
- X for (cp = lp->l_cmd; cp; cp = cp->c_next)
- X#ifdef os9
- X fprintf(stderr, "- %s\n", cp->c_cmd);
- X#else
- X fprintf(stderr, "-\t%s\n", cp->c_cmd);
- X#endif
- X fputc('\n', stderr);
- X }
- X fputc('\n', stderr);
- X }
- X}
- X
- X
- X/*
- X * Recursive routine that does the actual checking.
- X */
- Xvoid
- Xcheck(np)
- X struct name *np;
- X{
- X register struct depend *dp;
- X register struct line *lp;
- X
- X
- X if (np->n_flag & N_MARK)
- X fatal("Circular dependency from %s", np->n_name);
- X
- X np->n_flag |= N_MARK;
- X
- X for (lp = np->n_line; lp; lp = lp->l_next)
- X for (dp = lp->l_dep; dp; dp = dp->d_next)
- X check(dp->d_name);
- X
- X np->n_flag &= ~N_MARK;
- X}
- X
- X
- X/*
- X * Look for circular dependancies.
- X * ie.
- X * a: b
- X * b: a
- X * is a circular dep
- X */
- Xvoid
- Xcirch()
- X{
- X register struct name *np;
- X
- X
- X for (np = namehead.n_next; np; np = np->n_next)
- X check(np);
- X}
- X
- X
- X/*
- X * Check the target .PRECIOUS, and mark its dependentd as precious
- X */
- Xvoid
- Xprecious()
- X{
- X register struct depend *dp;
- X register struct line *lp;
- X register struct name *np;
- X
- X
- X if (!((np = newname(".PRECIOUS"))->n_flag & N_TARG))
- X return;
- X
- X for (lp = np->n_line; lp; lp = lp->l_next)
- X for (dp = lp->l_dep; dp; dp = dp->d_next)
- X dp->d_name->n_flag |= N_PREC;
- X}
- END_OF_FILE
- if test 2152 -ne `wc -c <'check.c'`; then
- echo shar: \"'check.c'\" unpacked with wrong size!
- fi
- # end of 'check.c'
- fi
- if test -f 'h.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'h.h'\"
- else
- echo shar: Extracting \"'h.h'\" \(2546 characters\)
- sed "s/^X//" >'h.h' <<'END_OF_FILE'
- X/*
- X * Include header for make
- X */
- X
- X
- X#ifndef uchar
- X#ifdef os9
- X#define uchar char
- X#define void int
- X#define fputc putc
- X#else
- X#define uchar unsigned char
- X#endif
- X#endif
- X
- X#define bool uchar
- X#define time_t long
- X#define TRUE (1)
- X#define FALSE (0)
- X#define max(a,b) ((a)>(b)?(a):(b))
- X
- X#define DEFN1 "makefile" /* Default names */
- X#ifdef unix
- X#define DEFN2 "Makefile"
- X#endif
- X#ifdef eon
- X#define DEFN2 "Makefile"
- X#endif
- X
- X#ifdef amiga
- X#define strcmp stricmp
- X#endif
- X
- X/* os9 is case insensitive */
- X
- X#define LZ (1024) /* Line size */
- X
- X
- X
- X/*
- X * A name. This represents a file, either to be made, or existant
- X */
- X
- Xstruct name {
- X struct name *n_next; /* Next in the list of names */
- X char *n_name; /* Called */
- X struct line *n_line; /* Dependencies */
- X time_t n_time; /* Modify time of this name */
- X uchar n_flag; /* Info about the name */
- X};
- X
- X#define N_MARK 0x01 /* For cycle check */
- X#define N_DONE 0x02 /* Name looked at */
- X#define N_TARG 0x04 /* Name is a target */
- X#define N_PREC 0x08 /* Target is precious */
- X#define N_DOUBLE 0x10 /* Double colon target */
- X
- X/*
- X * Definition of a target line.
- X */
- Xstruct line {
- X struct line *l_next; /* Next line (for ::) */
- X struct depend *l_dep; /* Dependents for this line */
- X struct cmd *l_cmd; /* Commands for this line */
- X};
- X
- X
- X/*
- X * List of dependents for a line
- X */
- Xstruct depend {
- X struct depend *d_next; /* Next dependent */
- X struct name *d_name; /* Name of dependent */
- X};
- X
- X
- X/*
- X * Commands for a line
- X */
- Xstruct cmd {
- X struct cmd *c_next; /* Next command line */
- X char *c_cmd; /* Command line */
- X};
- X
- X
- X/*
- X * Macro storage
- X */
- Xstruct macro {
- X struct macro *m_next; /* Next variable */
- X char *m_name; /* Called ... */
- X char *m_val; /* Its value */
- X uchar m_flag; /* Infinite loop check */
- X};
- X
- Xextern char *myname;
- Xextern struct name namehead;
- Xextern struct macro *macrohead;
- Xextern struct name *firstname;
- Xextern bool silent;
- Xextern bool ignore;
- Xextern bool rules;
- Xextern bool dotouch;
- Xextern bool quest;
- Xextern bool domake;
- Xextern char str1[];
- Xextern char str2[];
- Xextern int lineno;
- X
- Xchar *fgets();
- Xchar *index();
- Xchar *rindex();
- Xchar *malloc();
- Xextern int errno;
- X
- Xchar *getmacro();
- Xstruct macro *setmacro();
- Xvoid input();
- Xvoid error();
- Xvoid fatal();
- Xint make();
- Xstruct name *newname();
- Xstruct depend *newdep();
- Xstruct cmd *newcmd();
- Xvoid newline();
- Xchar *suffix();
- Xvoid touch();
- Xvoid makerules();
- Xchar *gettok();
- Xvoid precious();
- END_OF_FILE
- if test 2546 -ne `wc -c <'h.h'`; then
- echo shar: \"'h.h'\" unpacked with wrong size!
- fi
- # end of 'h.h'
- fi
- if test -f 'input.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'input.c'\"
- else
- echo shar: Extracting \"'input.c'\" \(7435 characters\)
- sed "s/^X//" >'input.c' <<'END_OF_FILE'
- X/*
- X * Parse a makefile
- X */
- X
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "h.h"
- X
- X
- Xstruct name namehead;
- Xstruct name *firstname;
- X
- Xchar str1[LZ]; /* General store */
- Xchar str2[LZ];
- X
- X
- X/*
- X * Intern a name. Return a pointer to the name struct
- X */
- Xstruct name *
- Xnewname(name)
- X char *name;
- X{
- X register struct name *rp;
- X register struct name *rrp;
- X register char *cp;
- X
- X
- X for
- X (
- X rp = namehead.n_next, rrp = &namehead;
- X rp;
- X rp = rp->n_next, rrp = rrp->n_next
- X )
- X if (strcmp(name, rp->n_name) == 0)
- X return rp;
- X
- X if ((rp = (struct name *) malloc(sizeof(struct name)))
- X == (struct name *) 0)
- X fatal("No memory for name");
- X rrp->n_next = rp;
- X rp->n_next = (struct name *) 0;
- X if ((cp = malloc((unsigned) strlen(name) + 1)) == (char *) 0)
- X fatal("No memory for name");
- X strcpy(cp, name);
- X rp->n_name = cp;
- X rp->n_line = (struct line *) 0;
- X rp->n_time = (time_t) 0;
- X rp->n_flag = 0;
- X
- X return rp;
- X}
- X
- X/*
- X * Delete the last created name.
- X */
- X
- Xdelname(np)
- Xstruct name *np;
- X{
- X if (namehead.n_next == np) {
- X namehead.n_next = np->n_next;
- X free(np);
- X }
- X}
- X
- X/*
- X * Add a dependant to the end of the supplied list of dependants.
- X * Return the new head pointer for that list.
- X */
- Xstruct depend *
- Xnewdep(np, dp)
- X struct name *np;
- X struct depend *dp;
- X{
- X register struct depend *rp;
- X register struct depend *rrp;
- X
- X
- X if ((rp = (struct depend *) malloc(sizeof(struct depend)))
- X == (struct depend *) 0)
- X fatal("No memory for dependant");
- X rp->d_next = (struct depend *) 0;
- X rp->d_name = np;
- X
- X if (dp == (struct depend *) 0)
- X return rp;
- X
- X for (rrp = dp; rrp->d_next; rrp = rrp->d_next);
- X
- X rrp->d_next = rp;
- X
- X return dp;
- X}
- X
- X
- X/*
- X * Add a command to the end of the supplied list of commands.
- X * Return the new head pointer for that list.
- X */
- Xstruct cmd *
- Xnewcmd(str, cp)
- X char *str;
- X struct cmd *cp;
- X{
- X register struct cmd *rp;
- X register struct cmd *rrp;
- X register char *rcp;
- X
- X
- X if (rcp = rindex(str, '\n'))
- X *rcp = '\0'; /* Loose newline */
- X
- X while (isspace(*str))
- X str++;
- X
- X if (*str == '\0') /* If nothing left, the exit */
- X return (struct cmd *) 0;
- X
- X if ((rp = (struct cmd *) malloc(sizeof(struct cmd)))
- X == (struct cmd *) 0)
- X fatal("No memory for command");
- X rp->c_next = (struct cmd *) 0;
- X if ((rcp = malloc((unsigned) strlen(str) + 1)) == (char *) 0)
- X fatal("No memory for command");
- X strcpy(rcp, str);
- X rp->c_cmd = rcp;
- X
- X if (cp == (struct cmd *) 0)
- X return rp;
- X
- X for (rrp = cp; rrp->c_next; rrp = rrp->c_next);
- X
- X rrp->c_next = rp;
- X
- X return cp;
- X}
- X
- X
- X/*
- X * Add a new 'line' of stuff to a target. This check to see
- X * if commands already exist for the target. If flag is set,
- X * the line is a double colon target.
- X *
- X * Kludges:
- X * i) If the new name begins with a '.', and there are no dependents,
- X * then the target must cease to be a target. This is for .SUFFIXES.
- X * ii) If the new name begins with a '.', with no dependents and has
- X * commands, then replace the current commands. This is for
- X * redefining commands for a default rule.
- X * Neither of these free the space used by dependents or commands,
- X * since they could be used by another target.
- X */
- Xvoid
- Xnewline(np, dp, cp, flag)
- X struct name *np;
- X struct depend *dp;
- X struct cmd *cp;
- X bool flag;
- X{
- X bool hascmds = FALSE; /* Target has commands */
- X register struct line *rp;
- X register struct line *rrp;
- X
- X
- X /* Handle the .SUFFIXES case */
- X if (np->n_name[0] == '.' && !dp && !cp) {
- X for (rp = np->n_line; rp; rp = rrp) {
- X rrp = rp->l_next;
- X free((char *) rp);
- X }
- X np->n_line = (struct line *) 0;
- X np->n_flag &= ~N_TARG;
- X return;
- X }
- X /* This loop must happen since rrp is used later. */
- X for
- X (
- X rp = np->n_line, rrp = (struct line *) 0;
- X rp;
- X rrp = rp, rp = rp->l_next
- X )
- X if (rp->l_cmd)
- X hascmds = TRUE;
- X
- X if (hascmds && cp && !(np->n_flag & N_DOUBLE))
- X /* Handle the implicit rules redefinition case */
- X if (np->n_name[0] == '.' && dp == (struct depend *) 0) {
- X np->n_line->l_cmd = cp;
- X return;
- X } else
- X error("Commands defined twice for target %s", np->n_name);
- X if (np->n_flag & N_TARG)
- X if (!(np->n_flag & N_DOUBLE) != !flag) /* like xor */
- X error("Inconsistent rules for target %s", np->n_name);
- X
- X if ((rp = (struct line *) malloc(sizeof(struct line)))
- X == (struct line *) 0)
- X fatal("No memory for line");
- X rp->l_next = (struct line *) 0;
- X rp->l_dep = dp;
- X rp->l_cmd = cp;
- X
- X if (rrp)
- X rrp->l_next = rp;
- X else
- X np->n_line = rp;
- X
- X np->n_flag |= N_TARG;
- X if (flag)
- X np->n_flag |= N_DOUBLE;
- X}
- X
- X
- X/*
- X * Parse input from the makefile, and construct a tree structure
- X * of it.
- X */
- Xvoid
- Xinput(fd)
- X FILE *fd;
- X{
- X char *p; /* General */
- X char *q;
- X struct name *np;
- X struct depend *dp;
- X struct cmd *cp;
- X bool dbl, getline();
- X
- X
- X if (getline(str1, fd)) /* Read the first line */
- X return;
- X
- X for (;;) {
- X if (str1[0] == '\t' || str1[0] == ' ') /* Rules without targets */
- X error("Rules not allowed here");
- X
- X p = str1;
- X
- X while (isspace(*p)) /* Find first target */
- X p++;
- X
- X while (((q = index(p, '=')) != (char *) 0) &&
- X (p != q) && (q[-1] == '\\')) { /* Find value */
- X register char *a;
- X
- X a = q - 1; /* Del \ chr; move rest back */
- X p = q;
- X while (*a++ = *q++);
- X }
- X
- X if (q != (char *) 0) {
- X register char *a;
- X
- X *q++ = '\0'; /* Separate name and val */
- X while (isspace(*q))
- X q++;
- X if (p = rindex(q, '\n'))
- X *p = '\0';
- X
- X p = str1;
- X if ((a = gettok(&p)) == (char *) 0)
- X error("No macro name");
- X
- X setmacro(a, q);
- X
- X if (getline(str1, fd))
- X return;
- X continue;
- X }
- X expand(str1);
- X p = str1;
- X
- X#if 0
- X while (((q = index(p, ':')) != (char *) 0) &&
- X (p != q) && (q[-1] == '\\')) { /* Find dependents */
- X register char *a;
- X
- X a = q - 1; /* Del \ chr; move rest back */
- X p = q;
- X while (*a++ = *q++);
- X }
- X#else
- X q = index(p, ':');
- X#endif
- X
- X if (q == (char *) 0)
- X error("No targets provided");
- X
- X /* Added by OIS to allow at most one : in target names */
- X
- X {
- X register char *a = q;
- X
- X while (*++a) {
- X if (*a == ' ' || *a == '\t') {
- X /* Found no more colons. Must have been first one. */
- X break;
- X }
- X if (*a == ':') {
- X /* Found second colon. This must be the separator. */
- X if (a != q+1) /* No double colon */
- X q = a;
- X break;
- X }
- X }
- X }
- X
- X *q++ = '\0'; /* Separate targets and dependents */
- X
- X if (*q == ':') { /* Double colon */
- X dbl = 1;
- X q++;
- X } else
- X dbl = 0;
- X
- X for (dp = (struct depend *) 0; ((p = gettok(&q)) != (char *) 0);)
- X /* get list of dep's */
- X {
- X np = newname(p); /* Intern name */
- X dp = newdep(np, dp);/* Add to dep list */
- X }
- X
- X *((q = str1) + strlen(str1) + 1) = '\0';
- X /* Need two nulls for gettok (Remember separation) */
- X
- X cp = (struct cmd *) 0;
- X if (getline(str2, fd) == FALSE) { /* Get commands */
- X while (str2[0] == '\t' || str2[0] == ' ') { /*OIS*0.80*/
- X cp = newcmd(&str2[0], cp);
- X if (getline(str2, fd))
- X break;
- X }
- X }
- X while ((p = gettok(&q)) != (char *) 0) { /* Get list of targ's */
- X np = newname(p); /* Intern name */
- X newline(np, dp, cp, dbl);
- X if (!firstname && p[0] != '.')
- X firstname = np;
- X }
- X
- X if (feof(fd)) /* EOF? */
- X return;
- X
- X strcpy(str1, str2);
- X }
- X}
- END_OF_FILE
- if test 7435 -ne `wc -c <'input.c'`; then
- echo shar: \"'input.c'\" unpacked with wrong size!
- fi
- # end of 'input.c'
- fi
- if test -f 'macro.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'macro.c'\"
- else
- echo shar: Extracting \"'macro.c'\" \(2582 characters\)
- sed "s/^X//" >'macro.c' <<'END_OF_FILE'
- X/*
- X * Macro control for make
- X */
- X
- X
- X#include "h.h"
- X#undef strcmp /*OIS*0.80*/
- X
- Xstruct macro *macrohead;
- X
- X
- Xstruct macro *
- Xgetmp(name)
- X register char *name;
- X{
- X register struct macro *rp;
- X
- X for (rp = macrohead; rp; rp = rp->m_next)
- X if (strcmp(name, rp->m_name) == 0)
- X return rp;
- X return (struct macro *) 0;
- X}
- X
- X
- Xchar *
- Xgetmacro(name)
- X char *name;
- X{
- X struct macro *mp;
- X
- X if (mp = getmp(name))
- X return mp->m_val;
- X else
- X return "";
- X}
- X
- X
- Xstruct macro *
- Xsetmacro(name, val)
- X char *name;
- X char *val;
- X{
- X register struct macro *rp;
- X register char *cp;
- X
- X
- X /* Replace macro definition if it exists */
- X for (rp = macrohead; rp; rp = rp->m_next)
- X if (strcmp(name, rp->m_name) == 0) {
- X free(rp->m_val); /* Free space from old */
- X break;
- X }
- X if (!rp) { /* If not defined, allocate space for new */
- X if ((rp = (struct macro *) malloc(sizeof(struct macro)))
- X == (struct macro *) 0)
- X fatal("No memory for macro");
- X
- X rp->m_next = macrohead;
- X macrohead = rp;
- X rp->m_flag = FALSE;
- X
- X if ((cp = malloc((unsigned) strlen(name) + 1)) == (char *) 0)
- X fatal("No memory for macro");
- X strcpy(cp, name);
- X rp->m_name = cp;
- X }
- X if ((cp = malloc((unsigned) strlen(val) + 1)) == (char *) 0)
- X fatal("No memory for macro");
- X strcpy(cp, val); /* Copy in new value */
- X rp->m_val = cp;
- X
- X return rp;
- X}
- X
- X
- X/*
- X * Do the dirty work for expand
- X */
- Xvoid
- Xdoexp(to, from, len, buf)
- X char **to;
- X char *from;
- X int *len;
- X char *buf;
- X{
- X register char *rp;
- X register char *p;
- X register char *q;
- X register struct macro *mp;
- X
- X
- X rp = from;
- X p = *to;
- X while (*rp) {
- X if (*rp != '$') {
- X *p++ = *rp++;
- X (*len)--;
- X } else {
- X q = buf;
- X if (*++rp == '{')
- X while (*++rp && *rp != '}')
- X *q++ = *rp;
- X else if (*rp == '(')
- X while (*++rp && *rp != ')')
- X *q++ = *rp;
- X else if (!*rp) {
- X *p++ = '$';
- X break;
- X } else
- X *q++ = *rp;
- X *q = '\0';
- X if (*rp)
- X rp++;
- X if (!(mp = getmp(buf)))
- X mp = setmacro(buf, "");
- X if (mp->m_flag)
- X fatal("Infinitely recursive macro %s", mp->m_name);
- X mp->m_flag = TRUE;
- X *to = p;
- X doexp(to, mp->m_val, len, buf);
- X p = *to;
- X mp->m_flag = FALSE;
- X }
- X if (*len <= 0)
- X error("Expanded line too long"); /*OIS*0.80*/
- X }
- X *p = '\0';
- X *to = p;
- X}
- X
- X
- X/*
- X * Expand any macros in str.
- X */
- Xvoid
- Xexpand(str)
- X char *str;
- X{
- X static char a[LZ];
- X static char b[LZ];
- X char *p = str;
- X int len = LZ - 1;
- X
- X strcpy(a, str);
- X doexp(&p, a, &len, b);
- X}
- END_OF_FILE
- if test 2582 -ne `wc -c <'macro.c'`; then
- echo shar: \"'macro.c'\" unpacked with wrong size!
- fi
- # end of 'macro.c'
- fi
- if test -f 'main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'main.c'\"
- else
- echo shar: Extracting \"'main.c'\" \(5539 characters\)
- sed "s/^X//" >'main.c' <<'END_OF_FILE'
- X/*
- X * make [-f makefile] [-ins] [target(s) ...]
- X *
- X * (Better than EON mk but not quite as good as UNIX make)
- X *
- X * -f makefile name
- X * -i ignore exit status
- X * -n Pretend to make
- X * -p Print all macros & targets
- X * -q Question up-to-dateness of target. Return exit status 1 if not
- X * -r Don't not use inbuilt rules
- X * -s Make silently
- X * -t Touch files instead of making them
- X * -m Change memory requirements (EON only)
- X */
- X
- X#include <stdio.h>
- X#include "h.h"
- X
- X#ifdef unix
- X#include <sys/errno.h>
- X#endif
- X#ifdef eon
- X#include <sys/err.h>
- X#endif
- X#ifdef os9
- X#include <errno.h>
- X#endif
- X#ifdef amiga
- X#include <errno.h>
- X#endif
- X
- X#ifdef eon
- X#define MEMSPACE (16384)
- X#endif
- X
- X
- Xchar *myname;
- Xchar *makefile; /* The make file */
- X#ifdef eon
- Xunsigned memspace = MEMSPACE;
- X#endif
- X
- XFILE *ifd; /* Input file desciptor */
- Xbool domake = TRUE; /* Go through the motions option */
- Xbool ignore = FALSE; /* Ignore exit status option */
- Xbool silent = FALSE; /* Silent option */
- Xbool print = FALSE; /* Print debuging information */
- Xbool rules = TRUE; /* Use inbuilt rules */
- Xbool dotouch = FALSE;/* Touch files instead of making */
- Xbool quest = FALSE; /* Question up-to-dateness of file */
- X
- X
- Xvoid
- Xmain(argc, argv)
- X register int argc;
- X register char **argv;
- X{
- X register char *p; /* For argument processing */
- X int estat = 0; /* For question */
- X register struct name *np;
- X void prt(), circh();
- X
- X
- X myname = (argc-- < 1) ? "make" : *argv++;
- X
- X while ((argc > 0) && (**argv == '-')) {
- X argc--; /* One less to process */
- X p = *argv++; /* Now processing this one */
- X
- X while (*++p != '\0') {
- X switch (*p) {
- X case 'f': /* Alternate file name */
- X if (*++p == '\0') {
- X if (argc-- <= 0)
- X usage();
- X p = *argv++;
- X }
- X makefile = p;
- X goto end_of_args;
- X#ifdef eon
- X case 'm': /* Change space requirements */
- X if (*++p == '\0') {
- X if (argc-- <= 0)
- X usage();
- X p = *argv++;
- X }
- X memspace = atoi(p);
- X goto end_of_args;
- X#endif
- X case 'n': /* Pretend mode */
- X domake = FALSE;
- X break;
- X case 'i': /* Ignore fault mode */
- X ignore = TRUE;
- X break;
- X case 's': /* Silent about commands */
- X silent = TRUE;
- X break;
- X case 'p':
- X print = TRUE;
- X break;
- X case 'r':
- X rules = FALSE;
- X break;
- X case 't':
- X dotouch = TRUE;
- X break;
- X case 'q':
- X quest = TRUE;
- X break;
- X default: /* Wrong option */
- X usage();
- X }
- X }
- Xend_of_args:;
- X }
- X
- X#ifdef amiga
- X if ((ifd = fopen("s:builtins.make", "r")) != (FILE *) 0) {
- X input(ifd);
- X fclose(ifd);
- X } else
- X#endif
- X makerules();
- X
- X#ifdef eon
- X if (initalloc(memspace) == 0xffff) /* Must get memory for alloc */
- X fatal("Cannot initalloc memory");
- X#endif
- X
- X if (!makefile) { /* If no file, then use default */
- X if ((ifd = fopen(DEFN1, "r")) == (FILE *) 0)
- X#ifdef eon
- X if (errno != ER_NOTF)
- X fatal("Can't open %s; error %02x", DEFN1, errno);
- X#endif
- X#ifdef unix
- X if (errno != ENOENT)
- X fatal("Can't open %s; error %02x", DEFN1, errno);
- X#endif
- X#ifdef amiga
- X if (errno != ENOENT)
- X fatal("Can't open %s; error %02x", DEFN1, errno);
- X#endif
- X#ifdef DEFN2
- X if ((ifd == (FILE *) 0)
- X && ((ifd = fopen(DEFN2, "r")) == (FILE *) 0))
- X fatal("Can't open %s", DEFN2);
- X#else
- X else
- X fatal("Can't open %s", DEFN1);
- X#endif
- X } else if (strcmp(makefile, "-") == 0) /* Can use stdin as makefile */
- X ifd = stdin;
- X else if ((ifd = fopen(makefile, "r")) == (FILE *) 0)
- X fatal("Can't open %s", makefile);
- X
- X setmacro("$", "$");
- X
- X while (argc && (p = index(*argv, '='))) {
- X char c;
- X
- X c = *p;
- X *p = '\0';
- X setmacro(*argv, p + 1);
- X *p = c;
- X
- X argv++;
- X argc--;
- X }
- X
- X input(ifd); /* Input all the gunga */
- X fclose(ifd); /* Finished with makefile */
- X lineno = 0; /* Any calls to error now print no line
- X * number */
- X
- X if (print)
- X prt(); /* Print out structures */
- X
- X np = newname(".SILENT");
- X if (np->n_flag & N_TARG)
- X silent = TRUE;
- X
- X np = newname(".IGNORE");
- X if (np->n_flag & N_TARG)
- X ignore = TRUE;
- X
- X precious();
- X
- X if (!firstname)
- X fatal("No targets defined");
- X
- X circh(); /* Check circles in target definitions */
- X
- X if (!argc)
- X estat = make(firstname, 0);
- X else
- X while (argc--) {
- X if (!print && !silent && strcmp(*argv, "love") == 0)
- X printf("Not war!\n");
- X estat |= make(newname(*argv++), 0);
- X }
- X
- X if (quest)
- X exit(estat);
- X else
- X exit(0);
- X}
- X
- X
- Xusage()
- X{
- X fprintf(stderr, "Usage: %s [-f makefile] [-inpqrst] [macro=val ...] [target(s) ...]\n", myname);
- X exit(1);
- X}
- X
- X
- Xvoid
- Xfatal(msg, a1, a2, a3, a4, a5, a6)
- X char *msg;
- X{
- X fprintf(stderr, "%s: ", myname);
- X fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
- X fputc('\n', stderr);
- X exit(1);
- X}
- X
- X#ifdef amiga /*OIS*0.80*/
- X
- X/*
- X * The Amiga case-insensitive filing system needs a case-insensitive
- X * filename comparison. Since strcmp() in this make is only applied to
- X * filenames, we simply replace it.
- X * Unfortunately, this also affects .PRECIOUS, .IGNORE, .SUFFIXES and
- X * .SILENT. Therefore, we need a hack, but that costs space, so we don't.
- X */
- X
- Xint lower(c)
- Xregister unsigned int c;
- X{
- X if (c >= 'A' && c <= 'Z')
- X return c - 'A' + 'a';
- X
- X return c;
- X}
- X
- Xint stricmp(first, second) /* Case-insensitive strcmp() */
- Xregister unsigned char *first, *second;
- X{
- X register int cmp;
- X
- X while (!(cmp = lower(*first++) - lower(*second++))) {
- X if (!first[-1]) return 0;
- X }
- X
- X return (cmp < 0) ? -1 : 1;
- X}
- X
- X/* Manx and PDC allow you to leave out Workbench code */
- X
- X_wb_parse(){}
- X
- X#endif
- END_OF_FILE
- if test 5539 -ne `wc -c <'main.c'`; then
- echo shar: \"'main.c'\" unpacked with wrong size!
- fi
- # end of 'main.c'
- fi
- if test -f 'make.n' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'make.n'\"
- else
- echo shar: Extracting \"'make.n'\" \(7344 characters\)
- sed "s/^X//" >'make.n' <<'END_OF_FILE'
- X.so an
- X.de HP
- X.ti -5
- X.en
- X.TH MAKE 1 "AMIGA Programmer's Manual"
- X.SH NAME
- Xmake - maintain program groups
- X.SH SYNTAX
- Xmake [ -f makefile ] [ option ] ... file ...
- X.SH DESCRIPTION
- X.I Make
- Xexecutes commands in
- X.I makefile
- Xto update one or more target
- X.I names. Name
- Xis typically a program. If no -f option
- Xis present, `makefile' and `Makefile' are tried in order.
- XIf
- X.I makefile
- Xis `-', the standard input is taken. More than one -f option may appear.
- X
- X.I Make
- Xupdates a target if it depends on prerequisite files that have been
- Xmodified since the target was last modified, or if the target does not
- Xexist.
- X
- X.I Makefile
- Xcontains a sequence of entries that specify dependencies. The first line of
- Xan entry is a blank-separated list of targets, then a colon, then a list of
- Xprerequisite files. Text following a semicolon, and all following lines
- Xthat begin with a tab, are shell commands to be executed to update the
- Xtarget. If a name appears on the left of more than one `colon' line, then
- Xit depends on all of the names on the right of the colon on those lines,
- Xbut only one command sequence may be specified for it. If a name appears on
- Xa line with a double colon :: then the command sequence following that line
- Xis performed only if the name is out of date with respect to the names to
- Xthe right of the double colon, and is not affected by other double colon
- Xlines on which that name may appear.
- X
- XTwo special forms of a name are recognized. A name like
- X.I a(b)
- Xmeans the file named
- X.I b
- Xstored in the archive named
- X.I a.
- XA name like
- X.I a((b))
- Xmeans the file stored in archive a containing the entry point
- X.I b.
- X
- XSharp and newline surround comments.
- X
- XThe following makefile says that `pgm' depends on two files `a.o' and
- X`b.o', and that they in turn depend on `.c' files and a common file `incl'.
- X
- X pgm: a.o b.o
- X cc a.o b.o -lm -o pgm
- X a.o: incl a.c
- X cc -c a.c
- X b.o: incl b.c
- X cc -c b.c
- X
- X.I Makefile
- Xentries of the form
- X
- X string1 = string2
- X
- Xare macro definitions. Subsequent appearances of
- X.I $(string1)
- Xor
- X.I ${string1}
- Xare replaced by
- X.I string2.
- XIf
- X.I string1
- Xis a single character, the parentheses or braces are optional.
- X
- X.I Make
- Xinfers prerequisites for files for which
- X.I makefile
- Xgives no construction commands. For example, a `.c' file may be inferred as
- Xprerequisite for a `.o' file and be compiled to produce the `.o' file. Thus
- Xthe preceding example can be done more briefly:
- X
- X pgm: a.o b.o
- X cc a.o b.o -lm -o pgm
- X a.o b.o: incl
- X
- XPrerequisites are inferred according to selected suffixes listed as the
- X`prerequisites' for the special name `.SUFFIXES'; multiple lists
- Xaccumulate; an empty list clears what came before. Order is significant;
- Xthe first possible name for which both a file and a rule as described in
- Xthe next paragraph exist is inferred. The default list is
- X
- X .SUFFIXES: .out .o .c .e .r .f .y .l .s .p
- X
- XThe rule to create a file with suffix
- X.I s2
- Xthat depends on a similarly named file with suffix
- X.I s1
- Xis specified as an entry for the `target'
- X.I s1s2.
- XIn such an entry, the special macro $* stands for the target name with
- Xsuffix deleted, $@@ for the full target name, $< for the complete list of
- Xprerequisites, and $? for the list of prerequisites that are out of date.
- XFor example, a rule for making optimized `.o' files from `.c' files is
- X
- X .c.o: ; cc -c -O -o $@@ $*.c
- X
- XCertain macros are used by the default inference rules to communicate
- Xoptional arguments to any resulting compilations. In particular, `CFLAGS'
- Xis used for
- X.I cc(1)
- Xoptions, `FFLAGS' for
- X.I f77(1)
- Xoptions, `PFLAGS' for
- X.I pc(1)
- Xoptions, and `LFLAGS' and `YFLAGS' for
- X.I lex
- Xand
- X.I yacc(1)
- Xoptions. In addition, the macro `MFLAGS' is filled in with the initial
- Xcommand line options supplied to
- X.I make.
- XThis simplifies maintaining a hierarchy of makefiles as one may then invoke
- X.I make
- Xon makefiles in subdirectories and pass along useful options such as -k.
- X
- XCommand lines are executed one at a time, each by its own shell. A line is
- Xprinted when it is executed unless the special target `.SILENT' is in
- X.I makefile,
- Xor the first character of the command is `@@'.
- X
- XCommands returning nonzero status (see
- X.I intro(1))
- Xcause
- X.I make
- Xto terminate unless the special target `.IGNORE' is in
- X.I makefile
- Xor the command begins with <tab><hyphen>.
- X
- XInterrupt and quit cause the target to be deleted unless the target is a
- Xdirectory or depends on the special name `.PRECIOUS'.
- X
- XOther options:
- X
- X.RS +5
- X.HP
- X-i@tEquivalent to the special entry `.IGNORE:'.
- X
- X.HP
- X-k@tWhen a command returns nonzero status, abandon work on the current
- Xentry, but continue on branches that do not depend on the current entry.
- X
- X.HP
- X-n@tTrace and print, but do not execute the commands needed to update the
- Xtargets.
- X
- X.HP
- X-t@tTouch, i.e. update the modified date of targets, without executing any
- Xcommands.
- X
- X.HP
- X-r@tEquivalent to an initial special entry `.SUFFIXES:' with no list.
- X
- X.HP
- X-s@tEquivalent to the special entry `.SILENT:'.
- X
- X.HP
- X-q@tQuestion up-to-dateness of target. Return exit status 1 if not;
- Xotherwise, return 0.
- X
- X.HP
- X-r@tDon't use built-in rules.
- X.RE
- X.SH FILES
- Xmakefile, Makefile
- X.SH "SEE ALSO"
- Xsh(1), touch(1), f77(1), pc(1)
- X.br
- XS. I. Feldman
- X.I "Make - A Program for Maintaining Computer Programs"
- X.SH BUGS
- XSome commands return nonzero status inappropriately. Use -i
- Xto overcome the difficulty.
- XCommands that are directly executed by the shell, notably
- X.I cd(1),
- Xare ineffectual across newlines in
- X.I make.
- X.SH "AMIGA VERSION"
- XNot all of the above applies to the Amiga version of
- X.I make.
- XIn particular, the default rules and suffixes are different.
- X
- XOmissions:
- X.br
- XLibraries and the related notation are not implemented.
- X.br
- XThe -k option is not supported.
- X.br
- XThe `;' construct is not implemented.
- X.br
- XThe remarks related to
- X.I MFLAGS, lex(1), yacc(1), f77(1)
- Xand
- X.I pc(1)
- Xdo not apply.
- X.br
- X$< and $? are not exactly as specified: $< is ONE prerequisite that is out
- Xof date (including path name), and $? is ALL prerequisites (without path
- Xnames).
- X
- XAdditions:
- X.br
- XIf a file
- X.I s:builtins.make
- Xexists, this file is used instead of the built-in rules.
- X.br
- XFilenames are not case-significant. Unfortunately, this also applies to the
- Xspecial target names .PRECIOUS, .IGNORE and .SILENT. These can also be
- Xspecified as .Precious, or .iGnOrE.
- X.br
- X.I Cd
- Xcommands are effective.
- X.br
- XComment characters (#) may be escaped with a backslash (\).
- X.br
- XAt most 1 colon is allowed in a target file name (for including device
- Xnames). In that case, the trailing colon must follow the target name
- Ximmediately, without any intervening white space. Spaces in the names are
- Xnot allowed.
- X.br
- XA new special target name has been added:
- X.it "@.PATH.
- XAny prerequisite names for
- X.it "@.PATH
- Xare used for finding source files for implicit rules. You name one or more
- Xdirectories, and if the source file for an implicit rule cannot be found
- Xin the current directory, each of the the given pathnames is prepended (in
- Xthe order given) to the source name, until the file is found.
- X
- XFor instance, the Makefile
- X
- X .PATH: src/ include/ src/old
- X
- X pgm: pgm.o
- X
- Xwill look (according to the .c.o rule) for pgm.c, src/pgm.c, include/pgm.c
- Xand src/oldpgm.c, in that order. Of course, due to other implicit rules,
- Xother files (with other suffixes) may be tried as well.
- END_OF_FILE
- if test 7344 -ne `wc -c <'make.n'`; then
- echo shar: \"'make.n'\" unpacked with wrong size!
- fi
- # end of 'make.n'
- fi
- if test -f 'reader.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'reader.c'\"
- else
- echo shar: Extracting \"'reader.c'\" \(2183 characters\)
- sed "s/^X//" >'reader.c' <<'END_OF_FILE'
- X/*
- X * Read in makefile
- X */
- X
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "h.h"
- X
- X
- Xint lineno;
- X
- X
- X/*
- X * Syntax error handler. Print message, with line number, and exits.
- X */
- Xvoid
- Xerror(msg, a1, a2, a3)
- X char *msg;
- X{
- X fprintf(stderr, "%s: ", myname);
- X fprintf(stderr, msg, a1, a2, a3);
- X if (lineno)
- X fprintf(stderr, " near line %d", lineno);
- X fputc('\n', stderr);
- X exit(1);
- X}
- X
- X
- X/*
- X * Read a line into the supplied string of length LZ. Remove
- X * comments, ignore blank lines. Deal with quoted (\) #, and
- X * quoted newlines. If EOF return TRUE.
- X */
- Xbool
- Xgetline(str, fd)
- X char *str;
- X FILE *fd;
- X{
- X register char *p;
- X register char *q; /*OIS*0.80*/
- X int pos = 0;
- X
- X
- X for (;;) {
- X if (fgets(str + pos, LZ - pos, fd) == (char *) 0)
- X return TRUE; /* EOF */
- X
- X lineno++;
- X
- X if ((p = index(str + pos, '\n')) == (char *) 0)
- X error("Line too long");
- X
- X if (p[-1] == '\\') {
- X register char space; /*OIS*0.80*/
- X /* p[-1] = '\n'; */ /*OIS*0.80*/
- X /* Skip the leading spaces of the next line */
- X while (space = getc(fd), space == ' ' || space == '\t');
- X p[-1] = space;
- X if (space != '\n') {
- X pos = p - str;
- X continue; /* read next line */
- X }
- X }
- X p = str;
- X while (((q = index(p, '#')) != (char *) 0) &&
- X (p != q) && (q[-1] == '\\')) {
- X char *a;
- X
- X a = q - 1; /* Del \ chr; move rest back */
- X p = q;
- X while (*a++ = *q++);
- X }
- X if (q != (char *) 0) {
- X q[0] = '\n';
- X q[1] = '\0';
- X }
- X p = str;
- X while (isspace(*p)) /* Checking for blank line */
- X p++;
- X
- X if (*p != '\0')
- X return FALSE;
- X pos = 0;
- X }
- X}
- X
- X
- X/*
- X * Get a word from the current line, surounded by white space.
- X * return a pointer to it. String returned has no white spaces
- X * in it.
- X */
- Xchar *
- Xgettok(ptr)
- X register char **ptr; /*OIS*0.80*/
- X{
- X register char *p;
- X
- X
- X while (isspace(**ptr)) /* Skip spaces */
- X (*ptr)++;
- X
- X if (**ptr == '\0') /* Nothing after spaces */
- X return NULL;
- X
- X p = *ptr; /* word starts here */
- X
- X while ((**ptr != '\0') && (!isspace(**ptr)))
- X (*ptr)++; /* Find end of word */
- X
- X *(*ptr)++ = '\0'; /* Terminate it */
- X
- X return (p);
- X}
- END_OF_FILE
- if test 2183 -ne `wc -c <'reader.c'`; then
- echo shar: \"'reader.c'\" unpacked with wrong size!
- fi
- # end of 'reader.c'
- fi
- if test -f 'rules.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rules.c'\"
- else
- echo shar: Extracting \"'rules.c'\" \(8196 characters\)
- sed "s/^X//" >'rules.c' <<'END_OF_FILE'
- X/*
- X * Control of the implicit suffix rules
- X */
- X
- X
- X#include "h.h"
- X#ifndef NULL
- X#define NULL ((void *) 0)
- X#endif
- X
- X/*
- X * Return a pointer to the suffix of a name
- X */
- Xchar *
- Xsuffix(name)
- X char *name;
- X{
- X return rindex(name, '.');
- X}
- X
- X
- X/*
- X * Dynamic dependency. This routine applies the suffis rules
- X * to try and find a source and a set of rules for a missing
- X * target. If found, np is made into a target with the implicit
- X * source name, and rules. Returns TRUE if np was made into
- X * a target.
- X */
- Xbool
- Xdyndep(np, pbasename, pinputname)
- X struct name *np;
- X char **pbasename; /* Name without suffix */
- X char **pinputname;
- X{
- X register char *p;
- X register char *q;
- X register char *suff; /* Old suffix */
- X register char *basename; /* Name without suffix */
- X struct name *op; /* New dependent */
- X struct name *sp; /* Suffix */
- X struct line *lp;
- X struct depend *dp;
- X struct name *pathnp; /* .PATH */
- X struct line *pathlp;
- X struct depend *pathdp;
- X struct depend *pathdp1;
- X char *newsuff;
- X char *path;
- X void modtime();
- X
- X
- X p = str1;
- X q = np->n_name;
- X if (!(suff = suffix(q)))
- X return FALSE; /* No suffix */
- X while (q < suff)
- X *p++ = *q++;
- X *p = '\0';
- X if ((*pbasename = basename = malloc(strlen(str1)+1)) == NULL)
- X fatal("No memory for basename");
- X strcpy(*pbasename, str1);
- X
- X if (!((sp = newname(".SUFFIXES"))->n_flag & N_TARG))
- X return FALSE;
- X
- X if (!((pathnp = newname(".PATH"))->n_flag & N_TARG))
- X pathnp = NULL;
- X
- X if ((pathnp) && (pathlp = pathnp->n_line))
- X pathdp = pathlp->l_dep;
- X else
- X pathdp = NULL;
- X
- X for (lp = sp->n_line; lp; lp = lp->l_next)
- X for (dp = lp->l_dep; dp; dp = dp->d_next) {
- X newsuff = dp->d_name->n_name; /* .c .o .asm etc */
- X if (strlen(suff) + strlen(newsuff) + 1 >= LZ)
- X fatal("Suffix rule too long");
- X p = str1;
- X q = newsuff;
- X while (*p++ = *q++);
- X p--;
- X q = suff;
- X while (*p++ = *q++);
- X sp = newname(str1); /* Form for example .c.o */
- X if (sp->n_flag & N_TARG) {
- X path = "";
- X pathdp1 = pathdp;
- X nextpath:
- X p = str1;
- X if (strlen(path) + strlen(basename) + strlen(newsuff) + 2 >= LZ)
- X fatal("Implicit name too long");
- X q = path;
- X while (*p++ = *q++); /* copy path */
- X p--;
- X q = basename;
- X while (*p++ = *q++); /* copy basename */
- X p--;
- X q = newsuff;
- X while (*p++ = *q++); /* copy new suffix */
- X op = newname(str1);
- X if (!op->n_line && !op->n_time)
- X modtime(op);
- X if (op->n_line || op->n_time) { /* file exists? */
- X dp = newdep(op, NULL);
- X newline(np, dp, sp->n_line->l_cmd, 0);
- X *pinputname = op->n_name; /* $< = path/basename.suffix */
- X return TRUE;
- X } else {
- X delname(op); /* Forget non-existing file */
- X if (pathdp1) { /* But is there a path? */
- X path = pathdp1->d_name->n_name;
- X pathdp1 = pathdp1->d_next;
- X goto nextpath;
- X }
- X }
- X }
- X }
- X return FALSE;
- X}
- X
- X
- X/*
- X * Make the default rules
- X */
- Xvoid
- Xmakerules()
- X{
- X register struct cmd *cp; /*OIS*0.80*/
- X register struct name *np; /*OIS*0.80*/
- X register struct depend *dp; /*OIS*0.80*/
- X
- X
- X#ifdef eon
- X setmacro("BDSCC", "asm");
- X /* setmacro("BDSCFLAGS", ""); */
- X cp = newcmd("$(BDSCC) $(BDSCFLAGS) -n $<", 0);
- X np = newname(".c.o");
- X newline(np, 0, cp, 0);
- X
- X setmacro("CC", "c");
- X setmacro("CFLAGS", "-O");
- X cp = newcmd("$(CC) $(CFLAGS) -c $<", 0);
- X np = newname(".c.obj");
- X newline(np, 0, cp, 0);
- X
- X setmacro("M80", "asm -n");
- X /* setmacro("M80FLAGS", ""); */
- X cp = newcmd("$(M80) $(M80FLAGS) $<", 0);
- X np = newname(".mac.o");
- X newline(np, 0, cp, 0);
- X
- X setmacro("AS", "zas");
- X /* setmacro("ASFLAGS", ""); */
- X cp = newcmd("$(ZAS) $(ASFLAGS) -o $@ $<", 0);
- X np = newname(".as.obj");
- X newline(np, 0, cp, 0);
- X
- X np = newname(".as");
- X dp = newdep(np, 0);
- X np = newname(".obj");
- X dp = newdep(np, dp);
- X np = newname(".c");
- X dp = newdep(np, dp);
- X np = newname(".o");
- X dp = newdep(np, dp);
- X np = newname(".mac");
- X dp = newdep(np, dp);
- X np = newname(".SUFFIXES");
- X newline(np, dp, 0, 0);
- X#endif
- X
- X/*
- X * Some of the UNIX implicit rules
- X */
- X#ifdef unix
- X setmacro("CC", "cc");
- X setmacro("CFLAGS", "-O");
- X#ifdef MINIXPC
- X cp = newcmd("$(CC) $(CFLAGS) -S $<", (struct cmd *)0);
- X np = newname(".c.s");
- X#else
- X cp = newcmd("$(CC) $(CFLAGS) -c $<", (struct cmd *)0);
- X np = newname(".c.o");
- X#endif MINIXPC
- X newline(np, (struct depend *)0, cp, 0);
- X
- X setmacro("AS", "as");
- X cp = newcmd("$(AS) -o $@ $<", (struct cmd *)0);
- X np = newname(".s.o");
- X newline(np, (struct depend *)0, cp, 0);
- X
- X setmacro("YACC", "yacc");
- X /* setmacro("YFLAGS", ""); */
- X cp = newcmd("$(YACC) $(YFLAGS) $<", (struct cmd *)0);
- X cp = newcmd("mv y.tab.c $@", cp);
- X np = newname(".y.c");
- X newline(np, (struct depend *)0, cp, 0);
- X
- X cp = newcmd("$(YACC) $(YFLAGS) $<", (struct cmd *)0);
- X#ifdef MINIXPC
- X cp = newcmd("$(CC) $(CFLAGS) -S y.tab.c", cp);
- X cp = newcmd("mv y.tab.s $@", cp);
- X np = newname(".y.s");
- X#else
- X cp = newcmd("$(CC) $(CFLAGS) -c y.tab.c", cp);
- X cp = newcmd("mv y.tab.o $@", cp);
- X np = newname(".y.o");
- X#endif MINIXPC
- X cp = newcmd("rm y.tab.c", cp);
- X newline(np, (struct depend *)0, cp, 0);
- X
- X setmacro("FLEX", "flex");
- X cp = newcmd("$(FLEX) $(FLEX_FLAGS) $<", (struct cmd *)0);
- X cp = newcmd("mv lex.yy.c $@", cp);
- X np = newname(".l.c");
- X newline(np, (struct depend *)0, cp, 0);
- X
- X cp = newcmd("$(FLEX) $(FLEX_FLAGS) $<", (struct cmd *)0);
- X#ifdef MINIXPC
- X cp = newcmd("$(CC) $(CFLAGS) -S lex.yy.s", cp);
- X cp = newcmd("mv lex.yy.s $@", cp);
- X np = newname(".l.s");
- X#else
- X cp = newcmd("$(CC) $(CFLAGS) -c lex.yy.c", cp);
- X cp = newcmd("mv lex.yy.o $@", cp);
- X np = newname(".l.o");
- X#endif MINIXPC
- X cp = newcmd("rm lex.yy.c", cp);
- X newline(np, (struct depend *)0, cp, 0);
- X
- X np = newname(".o");
- X dp = newdep(np, (struct depend *)0);
- X np = newname(".s");
- X dp = newdep(np, dp);
- X np = newname(".c");
- X dp = newdep(np, dp);
- X np = newname(".y");
- X dp = newdep(np, dp);
- X np = newname(".l");
- X dp = newdep(np, dp);
- X np = newname(".SUFFIXES");
- X newline(np, dp, (struct cmd *)0, 0);
- X#endif
- X
- X#ifdef os9
- X/*
- X * Fairlight use an enhanced version of the C sub-system.
- X * They have a specialised macro pre-processor.
- X */
- X setmacro("CC", "cc");
- X setmacro("CFLAGS", "-z");
- X cp = newcmd("$(CC) $(CFLAGS) -r $<", 0);
- X
- X np = newname(".c.r");
- X newline(np, 0, cp, 0);
- X np = newname(".ca.r");
- X newline(np, 0, cp, 0);
- X np = newname(".a.r");
- X newline(np, 0, cp, 0);
- X np = newname(".o.r");
- X newline(np, 0, cp, 0);
- X np = newname(".mc.r");
- X newline(np, 0, cp, 0);
- X np = newname(".mca.r");
- X newline(np, 0, cp, 0);
- X np = newname(".ma.r");
- X newline(np, 0, cp, 0);
- X np = newname(".mo.r");
- X newline(np, 0, cp, 0);
- X
- X np = newname(".r");
- X dp = newdep(np, 0);
- X np = newname(".mc");
- X dp = newdep(np, dp);
- X np = newname(".mca");
- X dp = newdep(np, dp);
- X np = newname(".c");
- X dp = newdep(np, dp);
- X np = newname(".ca");
- X dp = newdep(np, dp);
- X np = newname(".ma");
- X dp = newdep(np, dp);
- X np = newname(".mo");
- X dp = newdep(np, dp);
- X np = newname(".o");
- X dp = newdep(np, dp);
- X np = newname(".a");
- X dp = newdep(np, dp);
- X np = newname(".SUFFIXES");
- X newline(np, dp, 0, 0);
- X#endif
- X
- X#ifdef amiga
- X
- X#ifdef pdc /*OIS*0.80*/
- X static char ccx_c[] = "ccx -c";
- X
- X setmacro("CC", ccx_c);
- X#else
- X setmacro("CC", "cc");
- X#endif
- X cp = newcmd("$(CC) $(CFLAGS) $<", NULL);
- X np = newname(".c.o");
- X newline(np, NULL, cp, 0);
- X
- X#ifdef pdc /*OIS*0.80*/
- X setmacro("AS", ccx_c);
- X cp = newcmd("$(AS) $(AFLAGS) $<", NULL); /*OIS*0.80*/
- X#else
- X setmacro("AS", "as");
- X cp = newcmd("$(AS) $(AFLAGS) -o $@ $<", NULL); /*OIS*0.80*/
- X#endif
- X np = newname(".s.o");
- X newline(np, NULL, cp, NULL);
- X
- X np = newname(".o");
- X dp = newdep(np, NULL);
- X np = newname(".s");
- X dp = newdep(np, dp);
- X np = newname(".c");
- X dp = newdep(np, dp);
- X np = newname(".SUFFIXES");
- X newline(np, dp, NULL, 0);
- X#endif
- X}
- END_OF_FILE
- if test 8196 -ne `wc -c <'rules.c'`; then
- echo shar: \"'rules.c'\" unpacked with wrong size!
- fi
- # end of 'rules.c'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
- amiga@cs.odu.edu
- or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address )
- or ...!uunet!xanth!amiga ( very obsolescent mailers need this address )
-
- Comments, questions, and suggestions s should be addressed to ``amiga-request''
- (only use ``amiga'' for submissions) at the above addresses.
-